'''
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with self work for additional information
 * regarding copyright ownership.  The ASF licenses self file
 * to you under the Apache License, Version 2.0 (the
 * "License") you may not use self file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http:#www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
'''
from base.rdf.Seq import Seq
from base.rdf.SeqIndexBoundsException import SeqIndexBoundsException
from base.rdf.impl.ContainerImpl import ContainerImpl
from base.rdf.impl.LiteralImpl import LiteralImpl
from base.rdf.impl.SeqNodeIteratorFactoryImpl import SeqNodeIteratorFactoryImpl
from base.vocabulary.RDF import RDF
from base.graph.NodeFactory import NodeFactory

#import org.apache.jena.enhanced.*;
#import org.apache.jena.graph.*;
#import org.apache.jena.rdf.model.*;
#import org.apache.jena.vocabulary.RDF;

'''
 * An implementation of Seq
'''

class SeqImpl(ContainerImpl, Seq):

    # @SuppressWarnings("hiding")
    # param 
    # result Implementation factory = new
    # def Implementation factory = Implementation(self):
    #     # @Override
    # # param Node n, EnhGraph eg
    # # result boolean
    # def canWrap(self, n, eg):
    #         return True
    #
    #
    #     # @Override
    # # param Node n, EnhGraph eg
    # # result EnhNode
    # def wrap(self, n, eg):
    #         return SeqImpl(n, eg)
        
    # static NodeIteratorFactory
    seqIteratorFactory = SeqNodeIteratorFactoryImpl()

    '''
     * Creates SeqMem
    '''
    # param ModelCom model
    def __init__(self):
        super().__init__()

    def initWithModelCom(self, model):
        super().initWithModelCom(model)
        return self

    # param String uri, ModelCom model
    def initWithUriAndModelCom(self, uri, model):
        super().initWithUriAndModelCom(uri, model)
        return self
    

    # param Resource r, ModelCom m
    def initWithResourceAndModelCom(self, r, m):
        super().initWithResourceAndModelCom(r, m)
        return self
    

    # param Node n, EnhGraph g
    def initWithNodeAndEnhGraph(self, n, g):
        super().initWithNodeAndEnhGraph(n, g)
        return self
    

    # @Override
    # param int index
    # result Resource
    def getResource(self, index):
        return self.getRequiredProperty(RDF.li(index)).getResource()
    

    # @Override
    # param int index
    # result Literal
    def getLiteral(self, index):
        return self.getRequiredProperty(RDF.li(index)).getLiteral()
    

    # @Override
    # param int index
    # result RDFNode
    def getObject(self, index):
        return self.getRequiredProperty(RDF.li(index)).getObject()
    

    # @Override
    # param int index
    # result boolean
    def getBoolean(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getBoolean()
    

    # @Override
    # param int index
    # result byte
    def getByte(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getByte()
    

    # @Override
    # param int index
    # result short
    def getShort(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getShort()
    

    # @Override
    # param int index
    # result int
    def getInt(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getInt()
    

    # @Override
    # param int index
    # result long
    def getLong(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getLong()
    

    # @Override
    # param int index
    # result char
    def getChar(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getChar()
    

    # @Override
    # param int index
    # result float
    def getFloat(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getFloat()
    

    # @Override
    # param int index
    # result double
    def getDouble(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getDouble()
    

    # @Override
    # param int index
    # result String
    def getString(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getString()
    

    # @Override
    # param int index
    # result String
    def getLanguage(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getLanguage()
    

    # @Override
    # @Deprecated
    # param int index, ResourceF f
    # result Resource
    def getResourceWithIndexAndResourceFactory(self, index, f):
        return self.getRequiredProperty(RDF.li(index)).getResource(f)
    

    # @Override
    # param int index
    # result Bag
    def getBag(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getBag()
    

    # @Override
    # param int index
    # result Alt
    def getAlt(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getAlt()
    

    # @Override
    # param int index
    # result Seq
    def getSeq(self, index):
        self.checkIndex(index)
        return self.getRequiredProperty(RDF.li(index)).getSeq()
    

    # @Override
    # param int index, RDFNode o
    # result Seq
    def set(self, index, o):
        self.checkIndex(index)
        self.getRequiredProperty(RDF.li(index)).changeObject(o)
        return self
    

    # @Override
    # param int index, boolean o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeLiteralObject(o)
    #     return self
    

    # @Override
    # param int index, long o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeLiteralObject(o)
    #     return self
    

    # @Override
    # param int index, float o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeLiteralObject(o)
    #     return self
    

    # @Override
    # param int index, double o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeLiteralObject(o)
    #     return self
    

    # @Override
    # param int index, char o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeLiteralObject(o)
    #     return self
    

    # @Override
    # param int index, String o
    # result Seq
    # def set(self, index, o):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeObject(o)
    #     return self
    

    # @Override
    # param int index, String o, String l
    # result Seq
    # def set(self, index, o, l):
    #     self.checkIndex(index)
    #     self.getRequiredProperty(RDF.li(index)).changeObject(o, l)
    #     return self
    

    # @Override
    # param int index, Object o
    # result Seq
    def setWithIndexAndObj(self, index, o):
        self.checkIndex(index)
        # Statement
        s = self.getRequiredProperty(RDF.li(index))
        # Model
        m = s.getModel()
        # Statement
        s2 = m.createLiteralStatement(s.getSubject(), s.getPredicate(), o)
        s.getModel().remove(s)
        s.getModel().add(s2)
        #getRequiredProperty(RDF.li(index)).changeObject(o)
        return self
    

    # @Override
    # param int index, boolean o
    # result Seq
    def addPrimitive(self, index, o):
        return self.add(index, self.getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, long o
    # result Seq
    # def add(self, index, o):
    #     return add(index, getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, char o
    # result Seq
    # def add(self, index, o):
    #     return add(index, getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, float o
    # result Seq
    # def add(self, index, o):
    #     return add(index, getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, double o
    # result Seq
    # def add(self, index, o):
    #     return add(index, getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, Object o
    # result Seq
    # def add(self, index, o):
    #     return add(index, getModel().createTypedLiteral(o))
    

    # @Override
    # param int index, String o
    # result Seq
    # def add(self, index, o):
    #     return add(index, o, "")
    

    # @Override
    # param int index, String o, String l
    # result Seq
    # def add(self, index, o, l):
    #     return add(index, literal(o, l))
    

    # @Override
    # param int index, RDFNode o
    # result Seq
    def add(self, index, o):
        # int
        size = self.size()
        self.checkIndexWithMax(index, size + 1)
        self.shiftUp(index, size)
        self.addProperty(RDF.li(index), o)
        return self
    

    # @Override
    # param 
    # result NodeIterator
    def iterator(self):
        return self.listContainerMembers(self.seqIteratorFactory)
    

    # @Override
    # param Statement s
    # result Container
    def removeWithStatement(self, s):
        self.getModel().remove(s)
        self.shiftDown(s.getPredicate().getOrdinal() + 1, self.size() + 1)
        return self
    

    # @Override
    # param int index
    # result Seq
    def removeWithIndex(self, index):
        self.getRequiredProperty(RDF.li(index)).remove()
        self.shiftDown(index + 1, self.size() + 1)
        return self
    

    # @Override 继承原来的ContainerI
    # param int index, RDFNode o
    # result Container
    def remove(self, index, o):
        return self.removeWithStatement(self.getModel().createStatement(self, RDF.li(index), o).remove())
    

    # @Override
    # param RDFNode o
    # result int
    def indexOf(self, o):
        return self.containerIndexOf(o)
    

    # @Override
    # param boolean o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param long o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param char o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param float o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param double o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param Object o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(self.getModel().createTypedLiteral(o))
    

    # @Override
    # param String o
    # result int
    # def indexOf(self, o):
    #     return self.indexOf(o, "")
    

    # @Override
    # param String o, String l
    # result int
    def indexOfWithValueAndLang(self, o, l):
        return self.indexOf(self.literal(o, l))
    

    # param String s, String lang
    # result Literal
    def literal(self, s, lang):
        return LiteralImpl(NodeFactory.createLiteral(s, lang), self.getModelCom())
    

    # param int start, int finish
    # result void
    def shiftUp(self, start, finish):
        # Statement
        stmt = None
        # for (int i = finish i >= start i--):
        for i in range(finish, start - 1, -1):
            stmt = self.getRequiredProperty(RDF.li(i))
            self.getModel().remove(stmt)
            self.addProperty(RDF.li(i + 1), stmt.getObject())
        
    

    # param int start, int finish
    # result void
    def shiftDown(self, start, finish):
        # for (int i = start i <= finish i++):
        for i in range(start, finish + 1):
            # Statement
            stmt = self.getRequiredProperty(RDF.li(i))
            stmt.remove()
            self.addProperty(RDF.li(i - 1), stmt.getObject())
        
    

    # param int index
    # result void
    def checkIndex(self, index):
        self.checkIndexWithMax(index, self.size())
    

    # param int index, int max
    # result void
    def checkIndexWithMax(self, index, max):
        if not (1 <= index and index <= max):
            raise SeqIndexBoundsException(max, index)
        
    

